package org.chen.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.UpdateRequest;
import co.elastic.clients.elasticsearch.core.UpdateResponse;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.chen.aop.RefreshES;
import org.chen.model.elastic.ArticleIndex;
import org.chen.model.mongodb.ArticleDocument;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotEmpty;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ArticleSortService {

    private final MongoTemplate mongoTemplate;
    private final ElasticsearchClient esClient;

    public ArticleSortService(MongoTemplate mongoTemplate,
                              ElasticsearchClient esClient) {
        this.mongoTemplate = mongoTemplate;
        this.esClient = esClient;
    }

    // 更新置顶状态
    @Transactional
    @RefreshES
    public void updateTopStatus(String id, Boolean isTop, Integer topOrder) {
        if (topOrder == null) {
            topOrder = 0;
        }
        // 更新MongoDB
        Query query = Query.query(Criteria.where("id").is(id));
        Update update = new Update()
                .set("isTop", isTop)
                .set("topOrder", topOrder)
                .set("updateTime", new Date());
        mongoTemplate.updateFirst(query, update, ArticleDocument.class);

        // 更新ES
        updateEsArticleField(id, Map.of(
                "isTop", isTop,
                "topOrder", topOrder
        ));
    }

    // 更新热门状态
    @Transactional
    @RefreshES
    public void updateHotStatus(String id, Boolean isHot, Integer hotOrder) {
        if (hotOrder == null) {
            hotOrder = 0;
        }
        Query query = Query.query(Criteria.where("id").is(id));
        Update update = new Update()
                .set("isHot", isHot)
                .set("hotOrder", hotOrder)
                .set("updateTime", new Date());
        mongoTemplate.updateFirst(query, update, ArticleDocument.class);

        updateEsArticleField(id, Map.of(
                "isHot", isHot,
                "hotOrder", hotOrder
        ));
    }

    // 更新推荐状态
    @Transactional
    @RefreshES
    public void updateRecommendStatus(String id, Boolean isRecommend, Integer recommendOrder) {
        if (recommendOrder == null) {
            recommendOrder = 0;
        }
        Query query = Query.query(Criteria.where("id").is(id));
        Update update = new Update()
                .set("isRecommend", isRecommend)
                .set("recommendOrder", recommendOrder)
                .set("updateTime", new Date());
        mongoTemplate.updateFirst(query, update, ArticleDocument.class);

        updateEsArticleField(id, Map.of(
                "isRecommend", isRecommend,
                "recommendOrder", recommendOrder
        ));
    }

    // 更新ES中的字段
    private void updateEsArticleField(String id, Map<String, Object> fields) {
        try {
            // 构建 UpdateRequest
            UpdateRequest<ArticleIndex, Map<String, Object>> request = UpdateRequest.of(builder -> builder
                    .index("articles") // 索引名称
                    .id(id)            // 文档 ID
                    .doc(fields)       // 部分更新字段
            );
            // 执行更新操作
            UpdateResponse<ArticleIndex> response = esClient.update(request, ArticleIndex.class);

            log.info("Update successful for ID: {}. Result: {}", id, response.result());
        } catch (Exception e) {
            log.error("Failed to update ES article fields", e);
            throw new RuntimeException("Failed to update ES article fields", e);
        }
    }

    // 批量更新置顶状态
    @RefreshES
    public void batchUpdateTopStatus(List<String> ids, Boolean isTop, Integer topOrder) {
        try {
            // 1. 更新MongoDB
            Query query = Query.query(Criteria.where("id").in(ids));
            Update update = new Update()
                    .set("isTop", isTop)
                    .set("updateTime", new Date());

            if (isTop && topOrder != null) {
                update.set("topOrder", topOrder);
            } else {
                update.unset("topOrder");
            }

            UpdateResult mongoResult = mongoTemplate.updateMulti(query, update, ArticleDocument.class);
            log.info("Updated {} documents in MongoDB", mongoResult.getModifiedCount());

            // 2. 批量更新ES
            BulkRequest.Builder br = new BulkRequest.Builder();

            Map<String, Object> doc = new HashMap<>();
            doc.put("isTop", isTop);
            doc.put("updateTime", new Date());
            if (isTop && topOrder != null) {
                doc.put("topOrder", topOrder);
            }

            for (String id : ids) {
                br.operations(op -> op
                        .update(u -> u
                                .index("articles")
                                .id(id)
                                .action(a -> a
                                        .doc(doc)
                                )
                        )
                );
            }

            BulkResponse result = esClient.bulk(br.build());
            if (result.errors()) {
                log.error("Error updating documents in Elasticsearch");
                throw new RuntimeException("Failed to update articles in Elasticsearch");
            }

        } catch (Exception e) {
            log.error("Error updating articles top status", e);
            throw new RuntimeException("Failed to update articles top status", e);
        }
    }

    // 批量更新热门状态
    @RefreshES
    public void batchUpdateHotStatus(List<String> ids, Boolean isHot, Integer hotOrder) {
        try {
            // 1. 更新MongoDB
            Query query = Query.query(Criteria.where("id").in(ids));
            Update update = new Update()
                    .set("isHot", isHot)
                    .set("updateTime", new Date());

            if (isHot && hotOrder != null) {
                update.set("hotOrder", hotOrder);
            } else {
                update.unset("hotOrder");
            }

            UpdateResult mongoResult = mongoTemplate.updateMulti(query, update, ArticleDocument.class);
            log.info("Updated {} documents in MongoDB", mongoResult.getModifiedCount());

            // 2. 批量更新ES
            BulkRequest.Builder br = new BulkRequest.Builder();

            Map<String, Object> doc = new HashMap<>();
            doc.put("isHot", isHot);
            doc.put("updateTime", new Date());
            if (isHot && hotOrder != null) {
                doc.put("hotOrder", hotOrder);
            }

            for (String id : ids) {
                br.operations(op -> op
                        .update(u -> u
                                .index("articles")
                                .id(id)
                                .action(a -> a
                                        .doc(doc)
                                )
                        )
                );
            }

            BulkResponse result = esClient.bulk(br.build());
            if (result.errors()) {
                log.error("Error updating documents in Elasticsearch");
                throw new RuntimeException("Failed to update articles in Elasticsearch");
            }

        } catch (Exception e) {
            log.error("Error updating articles hot status", e);
            throw new RuntimeException("Failed to update articles hot status", e);
        }
    }

    // 批量更新推荐状态
    @RefreshES
    public void batchUpdateRecommendStatus(List<String> ids, Boolean isRecommend, Integer recommendOrder) {
        try {
            // 1. 更新MongoDB
            Query query = Query.query(Criteria.where("id").in(ids));
            Update update = new Update()
                    .set("isRecommend", isRecommend)
                    .set("updateTime", new Date());

            if (isRecommend && recommendOrder != null) {
                update.set("recommendOrder", recommendOrder);
            } else {
                update.unset("recommendOrder");
            }

            UpdateResult mongoResult = mongoTemplate.updateMulti(query, update, ArticleDocument.class);
            log.info("Updated {} documents in MongoDB", mongoResult.getModifiedCount());

            // 2. 批量更新ES
            BulkRequest.Builder br = new BulkRequest.Builder();

            Map<String, Object> doc = new HashMap<>();
            doc.put("isRecommend", isRecommend);
            doc.put("updateTime", new Date());
            if (isRecommend && recommendOrder != null) {
                doc.put("recommendOrder", recommendOrder);
            }

            for (String id : ids) {
                br.operations(op -> op
                        .update(u -> u
                                .index("articles")
                                .id(id)
                                .action(a -> a
                                        .doc(doc)
                                )
                        )
                );
            }

            BulkResponse result = esClient.bulk(br.build());
            if (result.errors()) {
                log.error("Error updating documents in Elasticsearch");
                throw new RuntimeException("Failed to update articles in Elasticsearch");
            }

        } catch (Exception e) {
            log.error("Error updating articles recommend status", e);
            throw new RuntimeException("Failed to update articles recommend status", e);
        }
    }
}
